package com.im.imservice.handler;

import com.alibaba.fastjson.JSON;
import com.im.imservice.config.CurrentChannelInfo;
import com.im.imservice.config.MessageAsyncSendCallback;
import com.im.imservice.config.SpringBeanUtil;
import com.im.imservice.dto.RequestInfo;
import com.im.imservice.enity.ImServerInfo;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

@Slf4j
public class WebSocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private static RocketMQTemplate rocketMQTemplate;

    private static MessageAsyncSendCallback asyncSendCallback;

    private final static String TAG = "record";

    private final static String TOP = "message_top:"+TAG;

    private final static String ZERO = "0";


    static {
        rocketMQTemplate =  SpringBeanUtil.getBean(RocketMQTemplate.class);
        asyncSendCallback =  SpringBeanUtil.getBean(MessageAsyncSendCallback.class);
    }


    private void broadcast(ChannelHandlerContext ctx, TextWebSocketFrame frame) {

//        if (frame instanceof CloseWebSocketFrame) {
//            ctx.channel().close();
//            return;
//        }
//        if (frame instanceof PingWebSocketFrame) {
//            ctx.channel().write(new PongWebSocketFrame(frame.content().retain()));
//            return;
//        }

        String request = frame.text();
        RequestInfo requestInfo = JSON.parseObject(request, RequestInfo.class);

        if (ZERO.equals(requestInfo.getMsgType())){
            log.info("心跳监听：" + request);
            return;
        }
        log.info("接收到客户端消息：" + request);
        /*
           判断用户是否在线
            如果在线先推送消息内容之接收者，在通过Mq 发送用户表存入聊天记录表中
            如果离线，将消息内容存入数据库中
         */
        String channelUserId = CurrentChannelInfo.getChannelUserId(ctx.channel());
        requestInfo.setRequestId(channelUserId);
        requestInfo.setCurrentTime(System.currentTimeMillis());
        if (CurrentChannelInfo.containsKey(requestInfo.getRecipientId())) {
            Channel channel = CurrentChannelInfo.getChannelGroupMap(requestInfo.getRecipientId());
            channel.writeAndFlush(new TextWebSocketFrame(request));
        }
        // 通过Mq插入数据库
        ImServerInfo imServerInfo = ImServerInfo.builder().tag(TAG).body(request).build();
        Message<ImServerInfo> msg = MessageBuilder.withPayload(imServerInfo).build();
        rocketMQTemplate.asyncSend(TOP, msg,asyncSendCallback);
    }


    /**
     * 在读取操作期间，有异常抛出时会调用。
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }



    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception{
        if (msg instanceof WebSocketFrame) {
            broadcast(ctx, msg);
        }else {
            /**
             * 如果不是 则调用下一个 handler处理请求
             */
            ctx.fireChannelRead(msg.retain());
        }
    }

}